package uark.csce.angli.wifidirectdemo;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;


public class WifiDirectDemo extends Activity {
    private static final String TAG = "WifiDirectDemo";

    String groupOwnerAddress;
    Button buttonBroadcast;
    EditText sendingMessage;
    TextView receivedMessage;
    IntentFilter intentFilter=new IntentFilter();
    WifiP2pManager wifiP2pManager;
    WifiP2pManager.Channel channel;
    List peersList=new ArrayList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wifi_direct_demo);

        buttonBroadcast=(Button)findViewById(R.id.buttonBroadcastMessage);
        sendingMessage=(EditText)findViewById(R.id.editMessage);
        receivedMessage=(TextView)findViewById(R.id.receivedMessage);

        initializeWifiDirect();
     // Indicates the state of Wi-Fi P2P connectivity has changed.
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    //  Indicates a change in the Wi-Fi P2P status.
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
     // Indicates a change in the list of available peers.
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
     // Indicates this device's details have changed.
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

        buttonBroadcast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                wifiP2pManager.discoverPeers(channel,actionListener);
                if (peersList.size()==0){
                    Log.e(TAG, "No Peers Found");
                    Toast.makeText(getApplicationContext(),"No peer found!",Toast.LENGTH_SHORT);
                }else if (peersList.size()>0)
                {
                    for (int i=0; i < peersList.size();i++)
                    {
                        Log.e(TAG, "Connecting to: " + peersList.get(i).toString());
                        connecTo((WifiP2pDevice) peersList.get(i));
                    }
                }
            }
        });

    }
    //Initialize WifiDirect
    public void initializeWifiDirect()
    {
        Log.e(TAG, "Initializing Wifi Direct");
        wifiP2pManager=(WifiP2pManager)getSystemService(Context.WIFI_P2P_SERVICE);
        channel=wifiP2pManager.initialize(this, getMainLooper(), new WifiP2pManager.ChannelListener() {
            @Override
            public void onChannelDisconnected()
            {
                Log.e(TAG, "onChannelDisconnected()");
                initializeWifiDirect();
            }
        });
    }

    
    //TODO:use to listen for changes to the System's Wi-Fi P2P state
    BroadcastReceiver broadcastReceiver=new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action=intent.getAction();
            if(action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)){
                Log.e(TAG, "WIFI_P2P_STATE_CHANGED_ACTION Received");
                int state=intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, WifiP2pManager.WIFI_P2P_STATE_DISABLED);
                if(state==WifiP2pManager.WIFI_P2P_STATE_ENABLED){

                }else {
                    Intent temIntent=new Intent(Settings.ACTION_WIFI_SETTINGS);
                    startActivity(temIntent);
                }

            }else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)){
                Log.e(TAG, "WIFI_P2P_PEERS_CHANGED_ACTION Received");
                if (wifiP2pManager!=null){
                    wifiP2pManager.requestPeers(channel,peerListListener);
                }
                Toast.makeText(getApplicationContext(),"Peers have changed",Toast.LENGTH_SHORT);

            }else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)){
                Log.e(TAG, "WIFI_P2P_CONNECTION_CHANGED_ACTION Received");
                NetworkInfo networkInfo=(NetworkInfo)intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
                if (networkInfo.isConnected()){
                    wifiP2pManager.requestConnectionInfo(channel,connectionInfoListener);
                }


            }
            else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)){
            	wifiP2pManager.requestPeers(channel, peerListListener);
            }
        }
    };

    //Listen for peerlist changes
    WifiP2pManager.PeerListListener peerListListener=new WifiP2pManager.PeerListListener() {
        @Override
        public void onPeersAvailable(WifiP2pDeviceList peers)
        {
            Log.e(TAG, "OnPeersAvailable: " + peers.getDeviceList().size());
            peersList.clear();
            peersList.addAll(peers.getDeviceList());
            //Toast.makeText(WifiDirectDemo.this, "Peers found: " + peersList.size(), Toast.LENGTH_SHORT).show();
        }
    };

    //Listen for connection state
    WifiP2pManager.ConnectionInfoListener connectionInfoListener=new WifiP2pManager.ConnectionInfoListener() {
        @Override
        public void onConnectionInfoAvailable(WifiP2pInfo info) {
            groupOwnerAddress = info.groupOwnerAddress.getHostAddress();
            Log.e(TAG, "OnConnectionInfoAvailable: Group Owner Address: " + groupOwnerAddress);
            if (info.groupFormed)
            {
                Log.e(TAG, "Group Formed!");
                if (info.isGroupOwner)
                    initServerSocket();
                else
                    initClientSocket(groupOwnerAddress);
            }

        }
    };

    private void initServerSocket(){
        String message= String.valueOf(sendingMessage.getText());
        Log.e(TAG, "Initiating server socket. Message: " + message);
        new ServerSocket(this).execute(message);



    }

    private void initClientSocket(final String hostAddress){

        Log.e(TAG, "Initiating client socket: Host Address: " + hostAddress);
        ClientSocket clientSocket =new ClientSocket(this);
        clientSocket.execute(hostAddress);

        Log.e(TAG, "Setting textview to: " + clientSocket.message);
        receivedMessage.setText(clientSocket.message);


    }

    public void connecTo(WifiP2pDevice device){
        WifiP2pConfig wifiP2pConfig=new WifiP2pConfig();
        wifiP2pConfig.deviceAddress=device.deviceAddress;
        wifiP2pConfig.groupOwnerIntent=0;
        wifiP2pManager.connect(channel,wifiP2pConfig,actionListener);
    }

    private WifiP2pManager.ActionListener actionListener=new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            Log.e(TAG, "ActionListener.onSuccess");
        }

        @Override
        public void onFailure(int reason) {
            String errorMessage = "WiFi Direct Failed: ";
            switch (reason){
                case WifiP2pManager.BUSY :
                    errorMessage += "Framework busy."; break;
                case WifiP2pManager.ERROR :
                    errorMessage += "Internal error."; break;
                case WifiP2pManager.P2P_UNSUPPORTED :
                    errorMessage += "Unsupported."; break;
                default:
                    errorMessage += "Unknown error."; break;
            }
            Log.e(TAG, "ActionListener.onFailure: Message: " + errorMessage);
            Toast.makeText(getApplicationContext(),errorMessage,Toast.LENGTH_SHORT);
        }


    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_wifi_direct_demo, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(broadcastReceiver,intentFilter);
    }

    @Override
    protected void onPause() {

        unregisterReceiver(broadcastReceiver);
        super.onPause();
    }
}
